package autotd.gui;
import autotd.*;


import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

import java.awt.image.BufferStrategy;

import java.io.*;
import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;


public class GUI extends JFrame implements AdvancedSimulatorListener {
	public static final GUI gui = new GUI();	// singleton, so that we don't have to pass references around everywhere
	public static void main(String[] args) {
	}
	
	
	private static final String nl = System.getProperty("line.separator");
	
	JMenuBar menuBar;
		JMenu file;
			JMenuItem newItem;
			JMenuItem infoItem;
			JMenuItem quitItem;
	JSplitPane main;
		JPanel jp;
		SimPanel display;
		JScrollPane consolePane;
			JTextArea console;

	InformationPanel infoPanel;
	JFileChooser loader;
	ButtonPanel buttonPanel;
	
	private TDSimulator sim;
	private autotd.server.Server server;
	
	private Timer updater = new Timer();
	private boolean updatedRecently = false;
	
	public GUI() {
		super("Automated Tower Defence");
		
		initialise();
		loader.addChoosableFileFilter(new ExtFileFilter("atd"));
		boolean success = false;
		String path = "src/autotd/files/testgame.atd";
		while ((path.length() > 0) && !newww(path)) {
			if (path.indexOf("/") > 0) {
				path = path.substring(path.indexOf("/")+1, path.length());
			} else {
				path = "";
			}
		}
	}
	
	public GUI(TDSimulator sim) {
		this();
		setSimulator(sim);
		
	}
	public void setSimulator(TDSimulator sim) {
		this.sim = sim;
		sim.addAdvancedListener(this);
		display.setSimulator(sim);
		buttonPanel.setSimulator(sim);
		infoPanel.setSimulator(sim);
		repaint();
	}
	
	public void initialise() {
		
		// try to make it look like a native app
		try {
			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());	// native LAF
		} catch (Exception e) {
			System.err.println("No native look-and-feel: "+e);
		}
		
		// setup menus
		menuBar = new JMenuBar();
		file = new JMenu();
		menuBar.add(file);
			file.setText("File");
			file.setMnemonic(KeyEvent.VK_F);
			newItem = new JMenuItem();
			file.add(newItem);
				newItem.setText("New...");
				newItem.setMnemonic(KeyEvent.VK_N);
				newItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, ActionEvent.CTRL_MASK));
			infoItem = new JMenuItem();
			file.add(infoItem);
				infoItem.setText("Show game info...");
				infoItem.setMnemonic(KeyEvent.VK_I);
				infoItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_I, ActionEvent.CTRL_MASK));
			quitItem = new JMenuItem();
			file.add(quitItem);
				quitItem.setText("Quit");
				quitItem.setMnemonic(KeyEvent.VK_Q);
				quitItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, ActionEvent.CTRL_MASK));
		super.setJMenuBar(menuBar);
		
		// setup panels
		buttonPanel  = new ButtonPanel();
		infoPanel = new InformationPanel();
		consolePane = new JScrollPane();
		console = new JTextArea();
		console.setRows(6);
		
		jp = new JPanel();
		jp.setLayout(new BorderLayout());
		display = new SimPanel();
		jp.add(display, BorderLayout.CENTER);
		jp.add(buttonPanel, BorderLayout.WEST);
		jp.add(infoPanel, BorderLayout.EAST);
		
		main = new JSplitPane();
		main.setOrientation(JSplitPane.VERTICAL_SPLIT);
		main.setOneTouchExpandable(true);
		main.setLeftComponent(jp);
		main.setResizeWeight(1.0d);
			
		main.setRightComponent(consolePane);
			consolePane.setViewportView(console);
		super.setContentPane(main);
		
		loader = new JFileChooser(System.getProperty("user.dir"));
		
		// setup listeners
		super.addWindowListener(
			new WindowAdapter() {
				public void windowClosing(WindowEvent e) {
					System.exit(0);
				}
			}
		);
		
		AL al = new AL();
		AbstractButton[] allItems = {newItem,infoItem,quitItem};
		for(AbstractButton ab: allItems) {
			ab.addActionListener(al);
		}
		
		
		// pack and display
		super.pack();
		super.setVisible(true);
	}
	
	
	private class AL implements ActionListener {
		public void actionPerformed(ActionEvent ae) {
			try{
			
			Object source = ae.getSource();
			       if (source== newItem ) {	neww();
			} else if (source== infoItem) {	info();
			} else if (source== quitItem) {	quit();
			}
			
			} catch(Exception e) {}	// catch any uncaught exceptions resulting from a user action
		}
	}
	
	public boolean newww(String file) {
		File f = new File(file);
		
		try {
			this.setSimulator(TDSimulator.loadSettings(f.getPath()));
			buttonPanel.init();
			//GUI.log("Profile successfully loaded from file \""+f.getPath()+"\"");
			server = new autotd.server.Server(sim);
			server.start();
			repaint();
			return true;
			
		} catch(IOException e) {
//			logException( "There was an IO problem loading the profile:",e );
		} catch(Exception e) {
//			logException( "There was an unknown problem loading the profile:",e );
		}
		return false;
	}
	
	
	public void neww() {
		int returnVal = loader.showOpenDialog(this);
		
		if (returnVal==JFileChooser.APPROVE_OPTION) {
			File f = loader.getSelectedFile();
			loader.setCurrentDirectory(f);
			
			try {
				this.setSimulator(TDSimulator.loadSettings(f.getPath()));
				buttonPanel.init();
				GUI.log("Profile successfully loaded from file \""+f.getPath()+"\"");
				server = new autotd.server.Server(sim);
				server.start();
				repaint();
				
			} catch(IOException e) {
				logException( "There was an IO problem loading the profile:",e );
			} catch(Exception e) {
				logException( "There was an unknown problem loading the profile:",e );
			}
		}
	}
	public void info() {
		
	}
	
	
	public void quit() {
		System.exit(0);
	}
	public void setTowerType(TowerType tt) {
		display.setPlaceTower(tt);
	}
	
	public static void log(String msg) {
		gui.logMessage(msg);
	}
	public void logMessage(String msg) {
		console.append(msg+nl);
		
		// scroll the pane to the bottom, by scrolling to make a 1*1 rectangle visible
		Rectangle bounds = console.getBounds();
		console.scrollRectToVisible(new Rectangle(0,bounds.height-1, 1,1));
	}
	public void logException(String description, Exception e) {
		String line = "--------------------------------------------------------------------------------";
		logMessage( description +nl+nl+ e.toString() +nl+nl+ "See standard error for more details." +nl+ line);
		System.err.println(line);
		System.err.println(description);
		System.err.println(e);
		System.err.println("Stack trace:");
		e.printStackTrace();
		System.err.println(line);
	}
	
	public void tick(int t){
		GUI.log("tick " + t);
		for (int i = 0; i < t; i++) tickOnce();
	}
	public void tickOnce() {
		if (sim!=null) sim.tick();
	}
	
	private class Update extends TimerTask {
		public void run() {
			updatedRecently = false;
			repaint();
		}
	}
	
	public void monsterCreated(int mID, String type, int level, int x, int y) {}
	public void monsterMoved(int mID, int prevX, int prevY, int currX, int currY) {}
	public void monsterInjured(int mID, int health) {}
	public void monsterCompletedPath(int mID) {}
	public void towerPlaced(int tID, String type, int x, int y, int height) {}
	public void towerFired(int tID, int mID) {}
	public void playerChange(int lives, int money) {}
	public void turnChangedTo(int turnNum) {}
}
